除了要處理各種工作室奇怪的問題之外,我其實是一名接案工程師,雖然目前已經不會再主動求案,但在早之前,其實都是必須在網路上四處找案子的。而為了避免淪為廉價奴工,所以我不太會去一些數字型外包網站,大部分的來源會是在 FB 社群或者 PTT code_job 版。
正所謂時間就是金錢,常常有人做版上發了是我有興趣的案子,但因為在忙較晚看到就變成「已發案」狀態了。所以那時候就寫了一隻爬蟲,每隔一段時間就去幫我查查看有沒有新發案,有的話就自動寄信給我,從此之後我考試每科都得 100 分,案子永遠第一個聯絡...
要探訪 PTT 基本上就是走 telnet,但小弟不學好,所以那部分就沒有涉獵了,好在 ptt 有網頁版,雖然會 delay 些時間,不過大致上還是可以接受的。
Code_job 版網址是 https://www.ptt.cc/bbs/CodeJob/index.html ,看起來挺容易爬的,雖然有分頁,但 index 預設就是最新的。
這時腦中就在思考,我如何才能取得最新的文章呢?把公告濾掉,然後直接抓最後一篇或許是個直覺的方法,但考量到可能新發案會突然短時間發出兩、三篇,所以這個方式並不完整。
接著又想,若我能去記錄上一次爬蟲拿到的最後一篇文章,就能知道這次爬蟲新抓取的篇數。這樣確實可行,但不簡潔,至少我要有個地方去記錄上次文章,要嘛就是 database,要嘛就是存 file,兩種都還要額外的心力去處理。
接著又想,若上面有時間的話,那我可以去比對時間,例如爬蟲五分鐘爬一次,那我就能去算五分鐘內生成的文章有多少。但事情看起來沒那麼簡單,畫面上只有日期,日期範圍又太大了。
持續觀察上面有的物件,突然瞄到一個有趣的東西,文章的連結。這個連結中,有一個 10 位數又 15 開頭的數字,憑著工程師強烈的第六感,這肯定就是 timestamp。
趕快驗證一下...
Bingo!那麼剩下都小事了...
我們把動作分解成幾個:
因為單純是 get request,我想應該也沒有研究的必要了XDDD,就直接來研究抓取 dom 就可以了。確認可以抓到文章列表,那剩下的就是 filter 的事情了。
先 define 一個 crontab 會抓取的時間數值
const CrontabPeriod = 60 * 60 * 24 * 3 // 先預設三天做測試,完成後再改回五分鐘
然後直接用 request 來抓取 code_job 版,然後再把文章 list 抓出來
request('https://www.ptt.cc/bbs/CodeJob/index.html', (err, res, body) => {
var $ = cheerio.load(body)
// 抓取文章列表
var list = $('.r-ent a').map((index, obj) => {
return {
title: $(obj).text(),
link: $(obj).attr('href'),
timestamp: $(obj).attr('href').substr(15, 10),
}
}).get()
console.log(list);
})
最後加入 timestamp 的 filter
// filter 時間
list = list.filter((post)=>{
return post.timestamp > (Date.now() / 1000 - CrontabPeriod)
})
const request = require('request');
const cheerio = require('cheerio');
const CrontabPeriod = 60 * 5 // 五分鐘抓一次
request('https://www.ptt.cc/bbs/CodeJob/index.html', (err, res, body) => {
var $ = cheerio.load(body)
// 抓取文章列表
var list = $('.r-ent a').map((index, obj) => {
return {
title: $(obj).text(),
link: $(obj).attr('href'),
timestamp: $(obj).attr('href').substr(15, 10),
}
}).get()
// filter 時間
list = list.filter((post)=>{
return post.timestamp > (Date.now() / 1000 - CrontabPeriod)
})
console.log(list);
})
我們可以透過 crontab 來設定每五分鐘 trigger 一次,同時加上 email server 來達到主動通知寄信,mail server 我們可以使用平常收發信用的 smtp,或者使用第三方的 service 像是 mailgun 之類的。
其實玩爬蟲並不是要多高深的技術或者,或多絢麗的技巧,真正有價值的是在於解決問題和省下時間。像是這次介紹的 ptt code_job 主動發文通知,就是一種很簡單,實作不困難,但卻能為我們省下許多的時間,而技術本意本該就是如此。
天啊好酷喔~我深深地被爬蟲吸引了~~
爬蟲很好玩的,任何自動化都能做,就怕你想不到爾已
真的好實用喔!!ptt 都是我的世界(我的世界都是ptt)